{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch.autograd import Variable\n",
    "import torch.nn as nn\n",
    "import torch.nn.init as init\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "import numpy as np\n",
    "from six.moves import cPickle as pickle\n",
    "from six.moves import range"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train set (97722, 1, 64, 64) (97722, 6)\n"
     ]
    }
   ],
   "source": [
    "pickle_file = 'SVHN_1x64x64_train.pickle'\n",
    "\n",
    "with open(pickle_file, 'rb') as f:\n",
    "    save = pickle.load(f)\n",
    "    train_dataset = save['train_dataset']\n",
    "    train_labels = save['train_labels']\n",
    "    del save  # hint to help gc free up memory\n",
    "    print('train set', train_dataset.shape, train_labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6227\n"
     ]
    }
   ],
   "source": [
    "c4 = []\n",
    "\n",
    "for i in range(97722):\n",
    "    categ = train_labels[i][0]\n",
    "    if(categ == 4):\n",
    "        c4.append(i)\n",
    "\n",
    "print(len(c4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6227, 1, 64, 64)\n",
      "(6227, 6)\n"
     ]
    }
   ],
   "source": [
    "c4_data = train_dataset[c4]\n",
    "c4_target = train_labels[c4]\n",
    "print(c4_data.shape)\n",
    "print(c4_target.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(1, 20, 3, padding=(1, 1))\n",
    "        self.conv2 = nn.Conv2d(20, 40, 3, padding=(1, 1))\n",
    "        self.conv3 = nn.Conv2d(40, 80, 3, padding=(1, 1))\n",
    "        self.conv4 = nn.Conv2d(80, 120, 3, padding=(1, 1))\n",
    "        self.conv5 = nn.Conv2d(120, 160, 3, padding=(1, 1))\n",
    "        self.conv6 = nn.Conv2d(160, 200, 3, padding=(1, 1))\n",
    "        self.conv7 = nn.Conv2d(200, 240, 3, padding=(1, 1))\n",
    "        self.pool = nn.MaxPool2d(2, 2)\n",
    "        self.FC = nn.Linear(960, 1080)\n",
    "        self.digitlength = nn.Linear(1080, 7)\n",
    "        self.digit1 = nn.Linear(1080, 10)\n",
    "        self.digit2 = nn.Linear(1080, 10)\n",
    "        self.digit3 = nn.Linear(1080, 10)\n",
    "        self.digit4 = nn.Linear(1080, 10)\n",
    "        self.digit5 = nn.Linear(1080, 10)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = self.pool(F.relu(self.conv2(x)))\n",
    "        x = F.relu(self.conv3(x))\n",
    "        x = self.pool(F.relu(self.conv4(x)))\n",
    "        x = self.pool(F.relu(self.conv5(x)))\n",
    "        x = self.pool(F.relu(self.conv6(x)))\n",
    "        x = self.pool(F.relu(self.conv7(x)))\n",
    "        x = x.view(-1, 960)\n",
    "        x = self.FC(x)\n",
    "        yl = self.digitlength(x)\n",
    "        y1 = self.digit1(x)\n",
    "        y2 = self.digit2(x)\n",
    "        y3 = self.digit3(x)\n",
    "        y4 = self.digit4(x)\n",
    "        y5 = self.digit5(x)\n",
    "        return [yl, y1, y2, y3, y4, y5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Net (\n",
       "  (conv1): Conv2d(1, 20, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv2): Conv2d(20, 40, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv3): Conv2d(40, 80, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv4): Conv2d(80, 120, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv5): Conv2d(120, 160, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv6): Conv2d(160, 200, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv7): Conv2d(200, 240, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (pool): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))\n",
       "  (FC): Linear (960 -> 1080)\n",
       "  (digitlength): Linear (1080 -> 7)\n",
       "  (digit1): Linear (1080 -> 10)\n",
       "  (digit2): Linear (1080 -> 10)\n",
       "  (digit3): Linear (1080 -> 10)\n",
       "  (digit4): Linear (1080 -> 10)\n",
       "  (digit5): Linear (1080 -> 10)\n",
       ")"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net = Net()\n",
    "f = open('c3_leg_ep_20.pkl', 'rb')\n",
    "net.load_state_dict(torch.load(f))\n",
    "f.close()\n",
    "net.cuda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for param in net.parameters():\n",
    "    print(param)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "for param in net.parameters():\n",
    "    if(param.grad is not None):\n",
    "        print(param)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.FloatTensor torch.Size([6227, 1, 64, 64])\n",
      "torch.LongTensor torch.Size([6227, 6])\n"
     ]
    }
   ],
   "source": [
    "c4_data_tensor = torch.from_numpy(c4_data)\n",
    "c4_target_tensor = torch.from_numpy(c4_target).type(torch.LongTensor)\n",
    "print(c4_data_tensor.type(), c4_data_tensor.size())\n",
    "print(c4_target_tensor.type(), c4_target_tensor.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "objective = nn.CrossEntropyLoss()\n",
    "optimizer = optim.Adam(net.parameters())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "97\n"
     ]
    }
   ],
   "source": [
    "num_epochs = 20\n",
    "batch_size = 64\n",
    "num_train =  c4_data.shape[0]\n",
    "iter_per_epoch = num_train // batch_size\n",
    "print_every = 40\n",
    "print(iter_per_epoch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "epoch_losses = {i:[] for i in range(num_epochs)}\n",
    "loss_history = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0/19\n",
      "--------------------------------------------------------------------------------------------------------------\n",
      "Iteration :  1  /  97\n",
      "loss :  5.085860252380371\n",
      "lossl :  0.00041174888610839844 loss1 :  0.3406800925731659 loss2 :  1.070333480834961 loss3 :  1.6604108810424805\n",
      "loss4 :  2.014024019241333\n",
      "Iteration :  41  /  97\n",
      "loss :  3.400709629058838\n",
      "lossl :  0.00016592442989349365 loss1 :  0.2866703271865845 loss2 :  0.6421934366226196 loss3 :  1.0729002952575684\n",
      "loss4 :  1.3987797498703003\n",
      "Iteration :  81  /  97\n",
      "loss :  3.4856481552124023\n",
      "lossl :  6.298720836639404e-05 loss1 :  0.34067440032958984 loss2 :  0.7340823411941528 loss3 :  1.1426481008529663\n",
      "loss4 :  1.2681803703308105\n",
      "time taken :  147.5708909034729\n",
      "--------------------------------------------------------------------------------------------------------------\n",
      "Epoch 1/19\n",
      "--------------------------------------------------------------------------------------------------------------\n",
      "Iteration :  1  /  97\n",
      "loss :  2.790579080581665\n",
      "lossl :  6.38812780380249e-05 loss1 :  0.09844815731048584 loss2 :  0.6653976440429688 loss3 :  0.8922945261001587\n",
      "loss4 :  1.1343748569488525\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-22-526edc5f3a7e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     35\u001b[0m         \u001b[0moptimizer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     36\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 37\u001b[0;31m         \u001b[0mloss_history\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfinal_loss\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     38\u001b[0m         \u001b[0mepoch_losses\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mepoch\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfinal_loss\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     39\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "for epoch in range(num_epochs):  # loop over the dataset multiple times\n",
    "    \n",
    "    print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n",
    "    print('-' * 110)\n",
    "\n",
    "    i = 0\n",
    "    rng_state = torch.get_rng_state()\n",
    "    new_idxs = torch.randperm(num_train)\n",
    "    c4_X = c4_data_tensor[new_idxs]\n",
    "    c4_Y = c4_target_tensor[new_idxs]\n",
    "    \n",
    "    t1 = time.time()\n",
    "    for t in range(iter_per_epoch):\n",
    "        \n",
    "        X_batch = c4_X[i: i+batch_size]\n",
    "        Y_batch = c4_Y[i: i+batch_size][:,0:5]\n",
    "        i += batch_size\n",
    "\n",
    "        Y_batch = Variable(Y_batch.cuda())\n",
    "        X_batch = Variable(X_batch.cuda())\n",
    "        \n",
    "        optimizer.zero_grad()\n",
    "        \n",
    "        outputs = net(X_batch)\n",
    "        \n",
    "        lossl = objective(outputs[0], Y_batch[:, 0])\n",
    "        loss1 = objective(outputs[1], Y_batch[:, 1])\n",
    "        loss2 = objective(outputs[2], Y_batch[:, 2])\n",
    "        loss3 = objective(outputs[3], Y_batch[:, 3])\n",
    "        loss4 = objective(outputs[4], Y_batch[:, 4])\n",
    "        final_loss = lossl + loss1 + loss2 + loss3 + loss4\n",
    "        \n",
    "        final_loss.backward()\n",
    "        \n",
    "        optimizer.step()\n",
    "        \n",
    "        loss_history.append(final_loss.data[0])\n",
    "        epoch_losses[epoch].append(final_loss.data[0])\n",
    "        \n",
    "        if (t % print_every == 0):\n",
    "            print('Iteration : ', t+1, ' / ', iter_per_epoch)\n",
    "            print('loss : ', final_loss.data[0])\n",
    "            print('lossl : ', lossl.data[0], 'loss1 : ', loss1.data[0], 'loss2 : ', loss2.data[0], 'loss3 : ', loss3.data[0])\n",
    "            print('loss4 : ', loss4.data[0])\n",
    "    t2 = time.time()\n",
    "    print(\"time taken : \", t2-t1)\n",
    "    print('-' * 110)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "f = open(\"c3_leg_ep_20.pkl\", \"bw\")\n",
    "torch.save(net.state_dict(), f)\n",
    "f.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f72ae11d748>]"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nTPREREnu/wMxRoyUi2/K/wAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f72ae21a2b0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure()\n",
    "plt.plot(loss_history)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
